/*
   Copyright 2009 Abdulla Abdurakhmanov (abdulla@latestbit.com)
   Original sources are available at www.latestbit.com

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

package org.latestbit.smartobjects.network.tcp.tests;

import java.nio.ByteBuffer;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.*;

import org.latestbit.smartobjects.network.*;

public class ConnectionListenerTester implements IConnectionListener, IStreamListener {
	private static final long DEFAULT_AWAIT_TIME = 25;
	private Lock conditionLock = new ReentrantLock();
	
	private Condition condition = conditionLock.newCondition();
	private boolean connected = false;
	private String errorMessage;
	private ByteBuffer receivedBuffer;
	private AtomicInteger receivedBufferSize = new AtomicInteger(0);

	public void waitCondition() throws InterruptedException, TimeoutException {
		if(!condition.await(DEFAULT_AWAIT_TIME, TimeUnit.SECONDS))
			throw new TimeoutException("Timeout occured for waiting event");
	}
	
	public boolean tryWaitCondition(long timeInSec) throws InterruptedException, TimeoutException {
		return condition.await(timeInSec, TimeUnit.SECONDS);
	}	
	
	public Lock getConditionLock() {
		return this.conditionLock;
	}
	
	public void signalCondition() {
		conditionLock.lock();
		condition.signal();
		conditionLock.unlock();
	}
	
	@Override
	public synchronized void onConnected(IConnection connection) {
		setConnected(true);
		setErrorMessage(null);
		signalCondition();
	}

	@Override
	public synchronized void onConnectionFailure(IConnection connection, String errorMessage) {
		setConnected(false);
		setErrorMessage(errorMessage);
		signalCondition();
	}

	@Override
	public synchronized  void onDisconnected(IConnection connection) {
		setConnected(false);
		setErrorMessage(null);
		signalCondition();
	}

	@Override
	public synchronized  void onReceiveError(IConnection connection, String errorMessage) {
		// TODO Auto-generated method stub

	}

	@Override
	public synchronized void onReceived(IConnection connection, ByteBuffer buffer) {
		this.receivedBufferSize.addAndGet(buffer.limit());
		this.receivedBuffer = buffer.duplicate();
		signalCondition();
	}

	@Override
	public synchronized  void onWriteError(IConnection connection, String errorMessage) {
	}

	public void setConnected(boolean connected) {
		this.connected = connected;
	}

	public boolean isConnected() {
		return connected;
	}

	private void setErrorMessage(String errorMessage) {
		this.errorMessage = errorMessage;
	}

	public String getErrorMessage() {
		return errorMessage;
	}

	public void setReceivedBuffer(ByteBuffer receivedBuffer) {
		this.receivedBuffer = receivedBuffer;
	}

	public ByteBuffer getReceivedBuffer() {
		return receivedBuffer;
	}
	
	public void resetReceivedBufferSize() {
		this.receivedBufferSize.set(0);
	}
	
	public int getReceivedBufferSize() {
		return this.receivedBufferSize.get();
	}

}
